home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
network
/
ka9q
/
nhclb120.zoo
/
command.asm
< prev
next >
Wrap
Assembly Source File
|
1992-02-11
|
11KB
|
523 lines
include pmacros.h
verify equ 0
dseg
if verify
verify_copy db 1,2,3,4,5,6,7,8,9
endif
db 4096 dup(?)
stack label byte
if verify
verify_original db 1,2,3,4,5,6,7,8,9
verify_len equ $-verify_original
verify_err db 'Stack overflow','$'
endif
dsegend
cseg
intds@ dw dgroup
segoff struc
offs dw ?
segm dw ?
segoff ends
their_8h dd ?
their_10h dd ?
their_13h dd ?
their_1Bh dd ?
their_21h dd ?
their_23h dd ?
their_24h dd ?
their_28h dd ?
dos_segment dw ? ;segment of internal DOS flags
indos_offset dw ? ;offset of INDOS flag
errflag_offset dw ? ;offset of critical error flag
program_status db 0 ;popup status
flag_10h db 0 ;status of interrupt 10h
flag_13h db 0 ;status of interrupt 13h
zflag db ? ;save and restore critical error.
dos_version db ? ;dos major version.
main_countdown db 20
ss_register dw ? ;SS register storage
sp_register dw ? ;SP register storage
my_psp dw ? ;our PSP.
their_psp dw ? ;PSP segment storage
tick_counter dw ?
indos_counter dw ?
errflag_counter dw ?
status_counter dw ?
bp_counter dw ?
main_counter dw ?
their_dta dd ?
;
;------------------------------------------------------------------------------
;Interrupt 8 handling routine.
;------------------------------------------------------------------------------
timer proc near
pushf ;call BIOS routine
call their_8h
inc tick_counter
cmp program_status,0 ;are we already running?
jne timer_status ;yes, then suspend ticking.
cmp flag_10h,0 ;video flag set?
jne timer_exit ;yes, then exit
cmp flag_13h,0 ;disk flag set?
jne timer_exit ;yes, then exit
push es ;save ES and DI
push di
mov es,dos_segment ;check INDOS flag
mov di,indos_offset
cmp byte ptr es:[di],0
jne timer_indos ;exit if it's set
mov di,errflag_offset ;check critical error flag
cmp byte ptr es:[di],0
jne timer_errflag ;exit if it's set
call main ;call body of program
pop di
pop es
timer_exit:
iret
timer_indos:
inc indos_counter
pop di ;restore registers
pop es
iret
timer_errflag:
inc errflag_counter
pop di ;restore registers
pop es
iret
timer_status:
inc status_counter
iret
timer endp
;
;------------------------------------------------------------------------------
;Interrupt 10h handling routine.
;------------------------------------------------------------------------------
video proc near
pushf ;push flags onto stack
inc flag_10h ;increment flag
call their_10h ;call BIOS routine
dec flag_10h ;decrement flag
iret
video endp
;
;------------------------------------------------------------------------------
;Interrupt 13h handling routine.
;------------------------------------------------------------------------------
my_13 proc far
pushf ;push flags onto stack
inc flag_13h ;set 'busy' flag
call their_13h ;call BIOS routine
pushf ;save output flags
dec flag_13h ;clear flag
popf ;restore output flags
ret 2 ;exit without destroying flags
my_13 endp
;
;------------------------------------------------------------------------------
;Interrupt 28h handling routine.
;------------------------------------------------------------------------------
my_28 proc near
pushf ;call original routine
call their_28h
inc bp_counter
cmp flag_10h,0 ;video flag set?
jne bp_exit ;yes, then exit
cmp flag_13h,0 ;disk flag set?
jne bp_exit ;yes, then exit
push es ;save ES and DI
push di
mov es,dos_segment ;check critical error flag
mov di,errflag_offset
cmp byte ptr es:[di],0
pop di ;clean up the stack
pop es
jne bp_errflag
call main ;call main routine
bp_exit:
iret ;done - exit
bp_errflag:
inc errflag_counter
iret ;done - exit
my_28 endp
;
;------------------------------------------------------------------------------
;Interrupt 21h handling routine.
;------------------------------------------------------------------------------
my_21 proc far
pushf ;save the flags
or ah,ah ;Doing function zero?
je jump_to_dos ;If yes, take the jump
cmp ah,4bh ;Doing EXEC function?
je jump_to_dos ;If yes, take the jump
popf
pushf
call cs:their_21h ;Do the DOS function
pushf ;Save the result flags
cmp cs:program_status,0 ;are we already running?
jne no_recursion ;yes, don't recurse.
dec cs:main_countdown
jne no_recursion
mov cs:main_countdown,20
call main ;Safe to access disk now
no_recursion:
popf ;Recover DOS result flags
sti ;Must return with interrupts on
ret 2 ;Return with DOS result flags
jump_to_dos:
popf
jmp cs:their_21h
my_21 endp
;
;------------------------------------------------------------------------------
;Interrupt 24h handling routine (DOS 3.X only).
;------------------------------------------------------------------------------
my_24 proc near
mov al,3 ;fail the call in progress
ioexit:
iret ;give control back to DOS
my_24 endp
;
;------------------------------------------------------------------------------
;MAIN is the routine called periodically.
;------------------------------------------------------------------------------
main proc near
inc main_counter
push ax
mov program_status,1 ;set program active flag
cli ;make sure interrupts are off
mov ss_register,ss ;save stack registers
mov sp_register,sp
mov ss,cs:intds@
mov sp,offset stack
sti ;enable interrupts
push bx
push cx
push dx
push si
push di
push ds
push es
push bp
;
;Set DS and ES segment registers.
;
push cs ;set DS to code segment
pop ds
dscode
if verify
call check_stack
endif
;
;Save the current active PSP address and activate this PSP.
;
mov zflag,0 ;clear flag
cmp dos_version,2 ;DOS version 2.X?
jne main5
mov es,dos_segment ;point ES:DI to INDOS
mov di,indos_offset
cmp byte ptr es:[di],0 ;INDOS clear?
je main5 ;yes, then branch
mov di,errflag_offset ;point ES:DI to error flag
cmp byte ptr es:[di],0 ;critical error flag clear?
jne main5 ;no, then branch
mov byte ptr es:[di],1 ;set critical error flag manually
mov zflag,1 ;set change flag
main5:
mov ah,51h ;get current PSP segment
int 21h
mov their_psp,bx ;save it
mov ah,50h ;make this the active PSP
mov bx,my_psp
int 21h
cmp zflag,0 ;ZFLAG clear?
je main6 ;yes, then branch
mov di,errflag_offset ;point ES:DI to error flag
mov byte ptr es:[di],0 ;restore error flag value
main6:
;
;Reset the interrupt 1Bh, 23h, and 24h vectors.
;
call ioset ;reset interrupt vectors
;
;Save the current dta and subdirectory
;
mov ah,2fh ;get disk transfer address
int 21h
mov their_dta.segm,es
mov their_dta.offs,bx
;
;Call the commutator loop of net until nothing gets queued up.
;
mov ds,intds@
assume ds:nothing
extproc cycle
call cycle@
;
;Restore the current dta and subdirectory
;
lds dx,their_dta
mov ah,1ah
int 21h
;
;Restore interrupt vectors and former active PSP.
;
mov ah,50h ;restore active PSP label
mov bx,their_psp
int 21h
call ioreset ;restore interrupt vectors
;
;Restore registers and stack before exit.
;
pop bp ;restore registers and exit
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
cli ;interrupts off
mov ss,ss_register ;switch to original stack
mov sp,sp_register
sti ;interrupts on
pop ax
mov program_status,0 ;clear status flag
ret
main endp
;
;------------------------------------------------------------------------------
;IOSET vectors interrupts 1Bh, 23h and 24h to internal handlers. IORESET
;restores the original vector values.
;------------------------------------------------------------------------------
ioset proc near
dscode
push es ;save ES
mov ax,351Bh ;get interrupt 1Bh vector
int 21h
mov their_1Bh.segm,es ;save it
mov their_1Bh.offs,bx
mov ah,25h ;point it to an IRET instruction
mov dx,offset ioexit
int 21h
mov ax,3523h ;get interrupt 23h vector
int 21h
mov their_23h.segm,es ;save it
mov their_23h.offs,bx
mov ah,25h ;point it to an IRET instruction
mov dx,offset ioexit
int 21h
mov ax,3524h ;get interrupt 24h vector
int 21h
mov their_24h.segm,es ;save it
mov their_24h.offs,bx
mov ah,25h ;then set it to IOERR routine
mov dx,offset my_24
int 21h
pop es ;restore ES
ret
ioset endp
;
ioreset proc near
a